/**
 * This file is Copyright © 2009 Vubble Limited. All Rights Reserved.
 */
package com.softwarecraftsmen.orogeny;

import com.softwarecraftsmen.orogeny.buildEnvironments.*;
import com.softwarecraftsmen.orogeny.execution.AllProperties;
import com.softwarecraftsmen.orogeny.execution.BuildExecuter;
import com.softwarecraftsmen.orogeny.filing.AbsoluteDirectory;
import com.softwarecraftsmen.orogeny.properties.Evaluatable;
import com.softwarecraftsmen.orogeny.properties.PropertyName;
import org.jetbrains.annotations.NotNull;

import java.io.File;
import static java.lang.System.currentTimeMillis;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.LinkedHashMap;
import static java.util.UUID.randomUUID;

public class BuildInstantiater
{
	private final Class<? extends BuildScript> buildScript;
	private final File scriptFileParentFolder;
	private final LinkedHashMap<PropertyName, Evaluatable> commandLineProperties;

	public BuildInstantiater(final @NotNull Class<? extends BuildScript> buildScript, final @NotNull File scriptFileParentFolder, final @NotNull LinkedHashMap<PropertyName, Evaluatable> commandLineProperties)
	{
		this.buildScript = buildScript;
		this.scriptFileParentFolder = scriptFileParentFolder;
		this.commandLineProperties = commandLineProperties;
	}

	@NotNull
	public BuildExecuter instantiate()
	{
		try
		{
			final BuildEnvironment buildEnvironment = concreteBuildEnvironment();
			final Method method = BuildScript.class.getDeclaredMethod("instantiate", Class.class, BuildEnvironment.class);
			method.setAccessible(true);
			return (BuildExecuter) method.invoke(null, buildScript, buildEnvironment);
		}
		catch (NoSuchMethodException e)
		{
			throw new IllegalStateException("Should never happen", e);
		}
		catch (IllegalAccessException e)
		{
			throw new IllegalStateException("Should never happen", e);
		}
		catch (IllegalArgumentException e)
		{
			throw new IllegalStateException(e);
		}
		catch (InvocationTargetException e)
		{
			throw new IllegalStateException(e.getCause());
		}
	}

	@NotNull
	private BuildEnvironment concreteBuildEnvironment()
	{
		final BaseDirectoryProcessor baseDirectoryProcessor = new BaseDirectoryProcessor(buildScript);
		final AbsoluteDirectory buildDirectory = new BuildDirectoryFinder(baseDirectoryProcessor).currentBuildDirectory(scriptFileParentFolder);
		return new ConcreteBuildEnvironment(buildScript.getName(), randomUUID(), new SimpleBuildDateTime(currentTimeMillis()), buildDirectory, new AllProperties(buildScript, commandLineProperties));
	}
}
